<template>
  <MainPage>
    <div v-if="hasTreeData" class="left-tree">
      <div class="left-search">
        <el-input v-model="searchText" placeholder="请输入" @keyup.native.enter="searchClick">
          <el-button slot="append" icon="el-icon-search" @click="searchClick"></el-button>
        </el-input>
        <el-button
          style="margin-left: 10px"
          type="primary"
          @click="
            addVariableLibraryClick(
              {
                isParent: true
              },
              'addVariableLibrary'
            )
          "
        >
          新建
        </el-button>
      </div>

      <el-empty
        v-if="searchNull"
        :image-size="70"
        style="padding-top: 10px"
        :description="`搜索的${pageType}库为空，请更换搜索条件`"
      ></el-empty>
      <div class="tree-wrap">
        <div v-for="(data, index) in treeData" :key="index" class="custom-tree-node">
          <div class="data-item" @click="expandClick(data)">
            <img :src="img.parentImg" />
            <span class="label" :title="data.propertyName">
              {{ data.propertyName }}
            </span>
            <span
              class="more-wrap"
              :class="currenEditId === data.id + data.propertyName && 'show'"
              @click.stop="rightClick(data)"
            >
              <i class="el-icon-more"></i>
              <div v-if="data.popoverVisible" class="popover" @click.stop>
                <div class="right-menu">
                  <div
                    class="right-menu-item"
                    @click="
                      addVariableLibraryClick(
                        {
                          pid: data.id
                        },
                        'addVariableSet'
                      )
                    "
                  >
                    新建
                  </div>
                  <div class="right-menu-item" @click="copyVariableLibraryClick(data, 'copyVariableLibrary')">
                    复制
                  </div>
                  <div class="right-menu-item" @click="delVariableLibraryClick(data)">删除</div>
                  <div class="right-menu-item" @click="editVariableLibraryClick(data, 'editVariableLibrary')">
                    编辑
                  </div>
                </div>
              </div>
            </span>
          </div>
          <div v-if="data.childrenVisible" class="children-item-wrap">
            <template v-if="data.children?.length">
              <div
                v-for="cdata in data.children"
                :key="cdata.id"
                class="children-item"
                :class="currentData.id === cdata.id && 'active'"
                @click="childrenItemClick(cdata)"
              >
                <div class="text">
                  <div class="label" :title="cdata.propertyName">
                    {{ cdata.propertyName }}
                  </div>
                  <!-- <div class="en-name" :title="cdata.propertyKey">{{ cdata.propertyKey }}</div> -->
                </div>
                <span
                  class="more-wrap"
                  :class="currenEditId === cdata.id + cdata.propertyName && 'show'"
                  @click.stop="rightClick(cdata)"
                >
                  <i class="el-icon-more"></i>
                  <div v-if="cdata.popoverVisible" class="popover" @click.stop>
                    <div class="right-menu">
                      <div class="right-menu-item" @click="copyVariableLibraryClick(cdata, 'copyVariableSet')">
                        复制
                      </div>
                      <div class="right-menu-item" @click="delVariableLibraryClick(cdata)">删除</div>
                      <div class="right-menu-item" @click="editVariableLibraryClick(cdata, 'editVariableSet')">
                        编辑
                      </div>
                    </div>
                  </div>
                </span>
              </div>
            </template>
            <el-empty v-else :image-size="70" style="padding: 10px 0" :description="`${pageType}集为空`">
              <div
                class="empty-add"
                @click="
                  addVariableLibraryClick(
                    {
                      pid: data.id
                    },
                    'addVariableSet'
                  )
                "
              >
                新建{{ pageType }}集
                <svg-icon icon-class="add"></svg-icon>
              </div>
            </el-empty>
          </div>
        </div>
      </div>
    </div>
    <el-empty v-else :image-size="70" style="padding-top: 10px" :description="`${pageType}库为空`">
      <span
        class="empty-add"
        @click="
          addVariableLibraryClick(
            {
              isParent: true
            },
            'addVariableLibrary'
          )
        "
      >
        新建{{ pageType }}库
        <svg-icon icon-class="add"></svg-icon>
      </span>
    </el-empty>

    <el-dialog :title="dialogData.title" :visible.sync="dialogData.visible" width="30%">
      <MyForm
        v-if="dialogData.visible"
        ref="myForm"
        :form-conf="formConf"
        :form-data="dialogData"
        :rules="rules"
        label-width="65px"
      ></MyForm>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogCancelClick">取 消</el-button>
        <el-button type="primary" @click="dialogConfirmClick">确 定</el-button>
      </span>
    </el-dialog>
  </MainPage>
</template>

<script setup>
import { ref, set, computed } from 'vue'
import { MessageBox, Notification } from 'element-ui'
import {
  loadDataModelModuleModelList,
  loadDataModelModuleModuleList,
  searchDataByName,
  addDataModelModule,
  copyDataModelModule,
  deleteDataModelModule,
  updateDataModelModule
} from '@/api/rule-management'
import MyForm from '@/components/MyForm/index.vue'

import defaultSettings from '@/settings'
import { generateUUID, postMessage, receivedMessage } from '@/utils/index'

const props = defineProps({
  type: {
    type: Number,
    default: 1
  }
})
const pageType = computed(() => ({ 3: '变量' }[props.type]))
const currenEditId = ref('')
const clearPopover = () => {
  treeData.value?.forEach?.((item) => {
    item.popoverVisible = false
    item.children?.forEach?.((citem) => {
      citem.popoverVisible = false
    })
  })
  currenEditId.value = ''
  window.removeEventListener('click', clearPopover)
}
const emit = defineEmits(['item-change'])
const hasTreeData = ref(true)
const searchText = ref('')
const treeData = ref([])
const searchNull = ref(false)
let searchDataByNameRequestId = generateUUID()
const searchClick = () => {
  if (!searchText.value) {
    return getData()
  }
  if (defaultSettings.isWPF || defaultSettings.isCEF) {
    searchDataByNameRequestId = generateUUID()
    let message = {
      RequestUrl: process.env.VUE_APP_URL + '/dataModelModule/searchDataByName',
      RequestMethod: 'POST',
      Headers: {
        contentType: 'application/json'
      },
      QueryParameter: {},
      RequestBody: {
        type: props.type,
        searchName: searchText.value
      },
      WebInfo: {
        requestId: searchDataByNameRequestId
      }
    }
    postMessage(message)
  } else {
    searchDataByName({ type: props.type, searchName: searchText.value }).then(({ data }) => {
      getSearchDataByName(data)
    })
  }
}
const getSearchDataByName = (data) => {
  searchNull.value = !data.modelData.length

  data = data ?? []
  const childrenObj = data.moduleData.reduce((obj, item) => {
    if (obj[item.pid]) {
      obj[item.pid].push(item)
    } else {
      obj[item.pid] = [item]
    }
    return obj
  }, {})
  data.modelData.forEach((item) => {
    if (childrenObj[item.id]) {
      item.children = childrenObj[item.id]
      item.childrenVisible = true
    } else {
      item.childrenVisible = false
    }
  })

  const current = data.modelData.find((item) => item.children?.length)
  setCurrenData(current?.children?.[0] ?? {})
  treeData.value = data.modelData
}
let loadDataModelModuleModelListRequestId = generateUUID()
const getData = async () => {
  if (searchText.value) {
    return searchClick()
  }
  if (defaultSettings.isWPF || defaultSettings.isCEF) {
    loadDataModelModuleModelListRequestId = generateUUID()
    let message = {
      RequestUrl: process.env.VUE_APP_URL + '/dataModelModule/loadModelList',
      RequestMethod: 'POST',
      Headers: {
        contentType: 'application/json'
      },
      QueryParameter: {},
      RequestBody: {
        type: props.type
      },
      WebInfo: {
        requestId: loadDataModelModuleModelListRequestId
      }
    }
    postMessage(message)
  } else {
    loadDataModelModuleModelList({ type: props.type }).then((res) => {
      setData(res)
    })
  }
}
let loadDataModelModuleModuleListRequestId = generateUUID()
const setData = async (res) => {
  let data = res.data
  hasTreeData.value = !!data.length
  data?.forEach((item) => {
    item.isParent = true
    item.popoverVisible = false
    item.childrenVisible = false
  })
  if (data[0]) {
    if (!data[0]?.children?.length) {
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        loadDataModelModuleModuleListRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/dataModelModule/loadModuleList',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { type: props.type, pid: data[0].id },
          WebInfo: {
            requestId: loadDataModelModuleModuleListRequestId
          }
        }
        postMessage(message)
        treeData.value = data
        searchNull.value = false
      } else {
        loadDataModelModuleModuleList({ type: props.type, pid: data[0].id }).then((res) => {
          set(data[0], 'children', res.data)
          data[0].childrenVisible = true // eslint-disable-line require-atomic-updates
          setCurrenData(data[0]?.children?.[0] ?? {})
          treeData.value = data
          searchNull.value = false
        })
      }
    } else {
      data[0].childrenVisible = true // eslint-disable-line require-atomic-updates
      setCurrenData(data[0]?.children?.[0] ?? {})
      treeData.value = data
      searchNull.value = false
    }
  } else {
    setCurrenData({})
    treeData.value = data
    searchNull.value = false
  }
}

const currentData = ref({})
const currentVariableLibrary = ref({})
let loadNewDataModelModuleModuleListRequestId = generateUUID()
const expandClick = async (data) => {
  if (!data.children?.length) {
    currentVariableLibrary.value = data
    if (defaultSettings.isWPF || defaultSettings.isCEF) {
      loadNewDataModelModuleModuleListRequestId = generateUUID()
      let message = {
        RequestUrl: process.env.VUE_APP_URL + '/dataModelModule/loadModuleList',
        RequestMethod: 'POST',
        Headers: {
          contentType: 'application/json'
        },
        QueryParameter: {},
        RequestBody: { type: props.type, pid: data.id },
        WebInfo: {
          requestId: loadNewDataModelModuleModuleListRequestId
        }
      }
      postMessage(message)
    } else {
      loadDataModelModuleModuleList({ type: props.type, pid: data.id }).then((res) => {
        refrethTreeData(res)
      })
    }
  } else {
    data.childrenVisible = !data.childrenVisible // eslint-disable-line require-atomic-updates
    if (data.childrenVisible === true && data.children?.length && !data.children.includes(currentData.value)) {
      setCurrenData(data.children[0])
    }
  }
}
const refrethTreeData = (res) => {
  let data = treeData.value.find((item) => item.id === currentVariableLibrary.value.id)
  set(data, 'children', res.data)
  data.childrenVisible = !data.childrenVisible // eslint-disable-line require-atomic-updates
  if (data.childrenVisible === true && data.children?.length && !data.children.includes(currentData.value)) {
    setCurrenData(data.children[0])
  }
}

const rightClick = (data) => {
  treeData.value.forEach((item) => {
    data.id === item.id || (item.popoverVisible = false)
    item.children?.forEach((citem) => {
      data.id === citem.id || (citem.popoverVisible = false)
    })
  })
  currenEditId.value = data.id + data.propertyName
  data.popoverVisible = !data.popoverVisible
  window.addEventListener('click', clearPopover)
}
const childrenItemClick = (data) => {
  setCurrenData(data)
}
const setCurrenData = (data) => {
  currentData.value = data
  emit('item-change', data)
}
const initData = JSON.stringify({ visible: false, title: '', propertyName: '', propertyKey: '' })
const dialogData = ref(JSON.parse(initData))
const resetDialogData = () => {
  dialogData.value = JSON.parse(initData)
}
const dialogCancelClick = () => {
  resetDialogData()
}

const rules = {
  propertyName: [{ required: true, message: '中文名称不能为空', trigger: 'blur' }]
  // propertyKey: [{ required: true, message: '英文名称不能为空', trigger: 'blur' }]
}
const myForm = ref()
let operationDataModelModule = generateUUID()
const dialogConfirmClick = () => {
  const saveState = myForm.value.submitForm()
  if (saveState) {
    if (defaultSettings.isWPF || defaultSettings.isCEF) {
      let operation = ''
      let params = {}
      if (['addVariableLibrary', 'addVariableSet'].includes(dialogData.value.type)) {
        operation = 'add'
        params = {
          type: props.type,
          pid: dialogData.value.data.pid ?? null,
          propertyName: dialogData.value.propertyName,
          propertyKey: dialogData.value.propertyKey
        }
      } else if (['copyVariableLibrary', 'copyVariableSet'].includes(dialogData.value.type)) {
        operation = 'copy'
        params = {
          type: props.type,
          pid: dialogData.value.data.pid ?? null,
          id: dialogData.value.data.id,
          propertyName: dialogData.value.propertyName,
          propertyKey: dialogData.value.propertyKey
        }
      } else {
        operation = 'update'
        params = {
          type: props.type,
          pid: dialogData.value.data.pid ?? null,
          id: dialogData.value.data.id,
          propertyName: dialogData.value.propertyName,
          propertyKey: dialogData.value.propertyKey
        }
      }
      operationDataModelModule = generateUUID()
      let message = {
        RequestUrl: process.env.VUE_APP_URL + '/dataModelModule/' + operation,
        RequestMethod: 'POST',
        Headers: {
          contentType: 'application/json'
        },
        QueryParameter: {},
        RequestBody: params,
        WebInfo: {
          requestId: operationDataModelModule
        }
      }
      postMessage(message)
    } else {
      dialogData.value.fn().then((res) => {
        afterOperationDataModelModule(res)
      })
    }
  }
}
const afterOperationDataModelModule = (res) => {
  if (res.success) {
    if (dialogData.value.type === 'addVariableLibrary') {
      treeData.value.push({
        ...res.data,
        childrenVisible: true,
        isParent: true,
        popoverVisible: false
      })
    } else if (dialogData.value.type === 'addVariableSet') {
      let data = treeData.value.find((item) => item.id === res.data.pid)
      !data.children && (data.children = [])
      data.childrenVisible = true
      data.children.push(res.data)
      setCurrenData(res.data)
    } else if (dialogData.value.type === 'copyVariableLibrary') {
      treeData.value.push({
        ...res.data,
        childrenVisible: true,
        isParent: true,
        popoverVisible: false
      })
      setCurrenData(res.data?.children?.[0] ?? {})
    } else if (dialogData.value.type === 'copyVariableSet') {
      let data = treeData.value.find((item) => item.id === res.data.pid)
      data.children.push(res.data)
      setCurrenData(res.data)
    } else if (dialogData.value.type === 'editVariableLibrary') {
      let data = treeData.value.find((item) => item.id === res.data.id)
      data.propertyName = res.data.propertyName
      !data.children && (data.children = [])
      data.children = res.data.children
      data.childrenVisible = true
      setCurrenData(res.data?.children?.[0] ?? {})
    } else if (dialogData.value.type === 'editVariableSet') {
      let data = treeData.value.find((item) => item.id === res.data.pid)
      let index = data.children.findIndex((item) => item.id === res.data.id)
      data.children[index].propertyName = res.data.propertyName
      if (data.children[index].id !== currentData.value.id) {
        setCurrenData(data.children[index])
      }
    }
    Notification({
      type: 'success',
      title: '成功',
      message: dialogData.value.successMessage
    })
    resetDialogData()
  } else {
    Notification({
      type: 'error',
      title: '错误',
      message: res.message
    })
  }
}
const addVariableLibraryClick = (data, name) => {
  const fn = () =>
    addDataModelModule({
      type: props.type,
      pid: dialogData.value.data.pid ?? null,
      propertyName: dialogData.value.propertyName,
      propertyKey: dialogData.value.propertyKey
    })
  dialogData.value = {
    type: name,
    visible: true,
    title: `新增${pageType.value}${data.isParent ? '库' : '集'}`,
    propertyName: '',
    propertyKey: '',
    data,
    successMessage: '新增完成',
    fn
  }
}
const copyVariableLibraryClick = (data, name) => {
  const fn = () =>
    copyDataModelModule({
      type: props.type,
      pid: dialogData.value.data.pid ?? null,
      id: dialogData.value.data.id,
      propertyName: dialogData.value.propertyName,
      propertyKey: dialogData.value.propertyKey
    })
  dialogData.value = {
    type: name,
    visible: true,
    title: `复制${pageType.value}${data.isParent ? '库' : '集'}`,
    propertyName: data.propertyName,
    propertyKey: data.propertyKey,
    successMessage: '复制完成',
    data,
    fn
  }
}
const currentDelData = ref({})
let deleteDataModelModuleRequestId = generateUUID()
const delVariableLibraryClick = (data) => {
  MessageBox.confirm(`将删除该目录下全部数据，是否确认删除?`, '警告').then(() => {
    currentDelData.value = data
    if (defaultSettings.isWPF || defaultSettings.isCEF) {
      deleteDataModelModuleRequestId = generateUUID()
      let message = {
        RequestUrl: process.env.VUE_APP_URL + '/dataModelModule/delete',
        RequestMethod: 'POST',
        Headers: {
          contentType: 'application/json'
        },
        QueryParameter: {},
        RequestBody: {
          type: props.type,
          pid: data.pid,
          id: data.id
        },
        WebInfo: {
          requestId: deleteDataModelModuleRequestId
        }
      }
      postMessage(message)
    } else {
      deleteDataModelModule({
        type: props.type,
        pid: data.pid,
        id: data.id
      }).then((res) => {
        afterDelVariableLibraryClick(res)
      })
    }
  })
}
const afterDelVariableLibraryClick = (res) => {
  if (res.success) {
    Notification({
      type: 'success',
      title: '成功',
      message: '删除完成'
    })
    if (currentDelData.value.pid) {
      // 变量集
      let current = treeData.value.find((item) => item.id === currentDelData.value.pid)
      let index = current.children.findIndex((item) => item.id === currentDelData.value.id)
      current.children.splice(index, 1)
      if (currentData.value.id === currentDelData.value.id) {
        setCurrenData(current.children?.[0] ?? {})
      }
    } else {
      // 变量库
      let index = treeData.value.findIndex((item) => item.id === currentDelData.value.id)
      treeData.value.splice(index, 1)
      if (treeData.value.length > 0) {
        treeData.value[0].childrenVisible = true
      }
      setCurrenData(treeData.value?.[0]?.children?.[0] ?? {})
    }
  } else {
    Notification({
      type: 'error',
      title: '错误',
      message: res.message
    })
  }
}
const editVariableLibraryClick = (data, name) => {
  const fn = () =>
    updateDataModelModule({
      type: props.type,
      pid: dialogData.value.data.pid ?? null,
      id: dialogData.value.data.id,
      propertyName: dialogData.value.propertyName,
      propertyKey: dialogData.value.propertyKey
    })
  dialogData.value = {
    type: name,
    visible: true,
    title: `编辑${pageType.value}${data.isParent ? '库' : '集'}`,
    propertyName: data.propertyName,
    propertyKey: data.propertyKey,
    successMessage: '修改完成',
    data,
    fn
  }
}

getData()
const img = {
  parentImg: `
  BIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACuSURBVHgB3ZE9CsJAEI
  XfxE2VINpZBmysPICVFvY5ghfyDh7BI9jYWHmDBLSxEcEugUwm2Soh/wsp8sGwC2/f47EDGEJ8QSCnV6Hd6I
  RDlwBu0K8yv3o3QpVfVnvA9aqe+LXm71NP1oD/Afcm84iX+L5m2DYGEcdQuXnmyLhFMfq0B4hX/8F8Bzjbov
  g+owvEjw3DAN1geZQtlBq8RmpgwZAJBCiQ5YOSBYaQIEwBQJ5eSQpxq34AAAAASUVORK5CYII=`,
  childImg: `
  IWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACASURBVHgB7Y4xDkBAEEX
  /bjQSjVLnAA7BEZzNQbgBNaVS4wAkCh2ylt1qLSIKW3jFzCQz82aAryFbYGkQ8tJXegOJ6+xOYElNzjWHJmu
  SCI5/sjq3xItbIbCZ/EVhrHLQTr9P7f20ELiLfmgqgb7EFRQv+QUmCCyZCzyFkQFGsAIn4xibXPu8wQAAAAB
  JRU5ErkJggg==`
}

// 表单配置
const formConf = computed(() => [
  {
    label: '名称',
    type: 'input',
    prop: 'propertyName',
    otherProps: {
      style: { width: '100%' },
      maxlength: '50',
      paddingRight: 45,
      'show-word-limit': true
    }
  }
  // {
  //   label: '英文名称',
  //   prop: 'propertyKey',
  //   type: 'input',
  //   otherProps: {
  //     maxlength: '20',
  //     paddingRight: 45,
  //     'show-word-limit': true
  //   }
  // }
])

const dataHandle = (result) => {
  let e = defaultSettings.isWPF ? result : { data: JSON.parse(result) }
  if (e.data.webInfo.requestId === loadDataModelModuleModelListRequestId) {
    setData(e.data.response)
  } else if (e.data.webInfo.requestId === searchDataByNameRequestId) {
    getSearchDataByName(e.data.response.data)
  } else if (e.data.webInfo.requestId === loadDataModelModuleModuleListRequestId) {
    set(treeData.value[0], 'children', e.data.response.data)
    treeData.value[0].childrenVisible = true // eslint-disable-line require-atomic-updates
    setCurrenData(treeData.value[0]?.children?.[0] ?? {})
  } else if (e.data.webInfo.requestId === loadNewDataModelModuleModuleListRequestId) {
    refrethTreeData(e.data.response)
  } else if (e.data.webInfo.requestId === operationDataModelModule) {
    afterOperationDataModelModule(e.data.response)
  } else if (e.data.webInfo.requestId === deleteDataModelModuleRequestId) {
    afterDelVariableLibraryClick(e.data.response)
  }
}
receivedMessage(dataHandle)
</script>

<style lang="less" scoped>
.left-tree {
  height: 100%;
  display: flex;
  flex-direction: column;
  // overflow-y: overlay;
  .left-search {
    padding-bottom: 10px;
    display: flex;
  }
  .tree-wrap {
    position: relative;
    flex: 1;
    margin-right: -14px;
    padding-right: 14px;
    overflow: hidden;
    &:hover {
      overflow-y: overlay;
    }
  }
  .custom-tree-node {
    .data-item,
    .children-item {
      display: flex;
      align-items: center;
      cursor: pointer;
      img {
        display: block;
      }
      .label {
        margin-left: 10px;
        margin-right: 2px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        color: #333333;
      }
      .svg-icon {
        font-size: 12px;
      }
      .more-wrap {
        margin-left: auto;
        position: relative;
        margin-right: 6px;
        display: none;
        &.show {
          display: block;
        }
      }
      &:hover {
        .more-wrap {
          display: block;
        }
      }
      .popover {
        position: absolute;
        z-index: 1000;
        background-color: #fff;
        top: 20px;
        left: -28px;
        width: 62px;
        .right-menu {
          padding: 6px 0;
          .right-menu-item {
            padding: 6px 0;
            text-align: center;

            &:hover {
              background-color: #b9c8dc;
              cursor: pointer;
            }
          }
        }
      }
    }
    .children-item {
      padding: 8px 0;
      display: flex;
      img {
        margin-left: 8px;
      }
      .el-icon-remove-outline {
        margin-left: auto;
      }
      &:hover,
      &.active {
        background-color: #dde4e9;
      }
      .text {
        flex: 1;
        min-width: 100px;
        .label {
          margin-left: 26px;
          width: 200px;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }

        .en-name {
          margin-left: 26px;
          color: #999999;
          font-size: 12px;
          padding-top: 5px;
          width: 200px;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      }

      .more-wrap {
        flex-shrink: 0;
      }
    }
    .data-item {
      padding: 8px 0;
    }
  }
}
.empty-add {
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  .svg-icon {
    font-size: 12px;
    margin-left: 5px;
  }
  cursor: pointer;
}
</style>
